#!/usr/bin/python
# -*- coding:utf8
from razb import xproduct, hyper,gen_A_B
from algo import *
#A - массив границ всей области, N1 - разбиение вдоль каждой оси, n - размерность пространства
#один гиперкуб
class Hyp:
   def __init__(self, A,N1,M,i,n):
     B=gen_A_B(A)
     GG=int(pow(N1,n))
     self.MM=M
     self.Integral = 0
     self.Disp=0
     self.boundary=(i,i+B*1.0/N1)
#много гиперкубов
class Hyp_space:
   def __init__(self, A,N1,M,n):
     self.g=[]
     for i in xproduct(hyper(N1+1,n,A)):
         self.g.append(Hyp(A,N1,M,i,n))
#метод - интегрирование сетки
   def integrio(self,f,n):
       Result_1=0.0
       Result_2=0.0
       num=0
       for k in self.g:
           num += 1
           print num 
           Z=MCint(f,n,int(k.MM),k.boundary[0],k.boundary[1])
           k.Integral = Z[0]
           k.Disp= Z[1]
           Result_1+=Z[0]
           Result_2+=Z[1]
       return (Result_1,Result_2)
#функция которая возвращает просуммированный по хорошим областям интеграл и удаляет хорошие области из списка гиперкубов
   def rem_xor(self,Disp_crit):
       Ini=0.0
       Dii=0.0
       for k in self.g:
           if k.Disp<=Disp_crit:

              Ini+=k.Integral
              Dii+=k.Disp
              self.g.remove(k)
       return (len(self.g),Ini,Dii)
#функция разбивает плохие гиперкубы N - число точек интегрирования в каждом новом гиперкубе
   def razbit(self,Disp_crit,N,n,N1):
       for k in self.g:
           ALL=[]
           if k.Disp >= Disp_crit:
              Al=[]
              for i in xrange(n):
                  Al.append((i,k.boundary[0][i],k.boundary[1][i]))
              ALL.append(Al)
       for u in ALL:
           for i in xproduct(hyper(N1+1,n,u)):
               self.g.append(Hyp(u,N1,N,i,n))

#функция, перераспределяющая точки интегрирования РАВНОМЕРНО! N - общее число точек
   def pererasp_uni(self,N):
       NN=len(self.g)
       N=int(N/NN)+1
       for k in self.g:
           k.MM=N
#функция, перераспределяющая точки интегрирования ПО ДИСПЕРСИИ!
   def pererasp_disp(self):
       return 0
